
#include <BLabel>
#include <BGridLayout>
#include <BVBoxLayout>
#include <BHBoxLayout>
#include <BGroupBox>

#include "StringUtils.h"
#include "HingeRestraintPanel.h"

HingeRestraintPanel::HingeRestraintPanel(BWidget* parent) : BWidget(parent)
{
	this->setTitle(BHingeRestraint::TypeName());

	BGridLayout* topLayout = new BGridLayout();
	{
		_nameAEdit = new BLineEdit();
		_pivotAEdit = new BLineEdit();
		_axisAEdit = new BLineEdit();
		_nameBEdit = new BLineEdit();
		_pivotBEdit = new BLineEdit();
		_axisBEdit = new BLineEdit();

		topLayout->addWidget(0, 0, new BLabel("nameA"));
		topLayout->addWidget(0, 1, _nameAEdit);
		topLayout->addWidget(1, 0, new BLabel("pointA"));
		topLayout->addWidget(1, 1, _pivotAEdit);
		topLayout->addWidget(2, 0, new BLabel("axisA"));
		topLayout->addWidget(2, 1, _axisAEdit);
		topLayout->addWidget(3, 0, new BLabel("nameB"));
		topLayout->addWidget(3, 1, _nameBEdit);
		topLayout->addWidget(4, 0, new BLabel("pointB"));
		topLayout->addWidget(4, 1, _pivotBEdit);
		topLayout->addWidget(5, 0, new BLabel("axisB"));
		topLayout->addWidget(5, 1, _axisBEdit);
	}

	BGroupBox* angularGroupBox = new BGroupBox("Angular Limit");
	{
		_hingeAngleSpinBox = new BRealSpinBox();
		_angleLowSpinBox = new BRealSpinBox();
		_angleHighSpinBox = new BRealSpinBox();

		BGridLayout* gridLayout = new BGridLayout(angularGroupBox);
		gridLayout->addWidget(2, 0, new BLabel("hinge-angle:"));
		gridLayout->addWidget(2, 1, _hingeAngleSpinBox);
		gridLayout->addWidget(3, 0, new BLabel("Angle Low"));
		gridLayout->addWidget(3, 1, _angleLowSpinBox);
		gridLayout->addWidget(4, 0, new BLabel("Angle High"));
		gridLayout->addWidget(4, 1, _angleHighSpinBox);
	}

	BGroupBox* motorGroupBox = new BGroupBox("Motor");
	{
		BHBoxLayout* hlayout1 = new BHBoxLayout();
		{
			_motorTargetSlider = new BRealSlider();
			_motorSwitchButton = new BButton();
			_motorSwitchButton->setCheckable(true);
			_motorSwitchButton->setText("Start", false);
			_motorSwitchButton->setText("Stop", true);
			hlayout1->addWidget(_motorTargetSlider);
			hlayout1->addWidget(_motorSwitchButton);
		}

		_motorTargetSpinBox = new BRealSpinBox();

		_motorVelocitySpinBox = new BRealSpinBox();

		_motorMaxMaxForceSpinBox = new BRealSpinBox();

		BGridLayout* gridLayout = new BGridLayout();
		gridLayout->addWidget(1, 0, new BLabel("Target"));
		gridLayout->addWidget(1, 1, _motorTargetSpinBox);
		gridLayout->addWidget(2, 0, new BLabel("Velocity"));
		gridLayout->addWidget(2, 1, _motorVelocitySpinBox);
		gridLayout->addWidget(3, 0, new BLabel("MaxForce"));
		gridLayout->addWidget(3, 1, _motorMaxMaxForceSpinBox);

		BVBoxLayout* vlayout = new BVBoxLayout(motorGroupBox);
		vlayout->addLayout(hlayout1);
		vlayout->addLayout(gridLayout);
	}

	BVBoxLayout* vlayout = new BVBoxLayout(this);
	vlayout->addLayout(topLayout);
	vlayout->addWidget(angularGroupBox);
	vlayout->addWidget(motorGroupBox);

	connect(this, Signal_AssetChanged, &HingeRestraintPanel::slotAssetChanged);

	connect(_nameAEdit, Signal_EditFinished, &HingeRestraintPanel::slotNameAEditFinished);
	connect(_pivotAEdit, Signal_EditFinished, &HingeRestraintPanel::slotPivotAEditFinished);
	connect(_axisAEdit, Signal_EditFinished, &HingeRestraintPanel::slotAxisAEditFinished);
	connect(_nameBEdit, Signal_EditFinished, &HingeRestraintPanel::slotNameBEditFinished);
	connect(_pivotBEdit, Signal_EditFinished, &HingeRestraintPanel::slotPivotBEditFinished);
	connect(_axisBEdit, Signal_EditFinished, &HingeRestraintPanel::slotAxisBEditFinished);

	connect(_angleLowSpinBox, Signal_EditFinished, &HingeRestraintPanel::slotAngleRangeEditFinished);
	connect(_angleHighSpinBox, Signal_EditFinished, &HingeRestraintPanel::slotAngleRangeEditFinished);

	connect(_motorSwitchButton, Signal_Toggled, &HingeRestraintPanel::slotMotorSwitchBoxToggled);
	connect(_motorTargetSlider, Signal_Sliding, &HingeRestraintPanel::slotMotorTargetSliding);
	connect(_motorTargetSpinBox, Signal_EditFinished, &HingeRestraintPanel::slotMotorTargetEditFinished);
	connect(_motorVelocitySpinBox, Signal_EditFinished, &HingeRestraintPanel::slotMotorVelocityEditFinished);
	connect(_motorMaxMaxForceSpinBox, Signal_EditFinished, &HingeRestraintPanel::slotMotorMaxForceEditFinished);
}
HingeRestraintPanel::~HingeRestraintPanel()
{

}

void HingeRestraintPanel::slotAssetChanged(BObject* object, const BValue& value)
{
	_hingeRestraint = value;
	if (_hingeRestraint)
	{
		_nameAEdit->setText(_hingeRestraint->bodyA()->name());
		_pivotAEdit->setText(StringFromVector(_hingeRestraint->pivotA()));
		_axisAEdit->setText(StringFromVector(_hingeRestraint->axisA()));
		_nameBEdit->setText(_hingeRestraint->bodyB()->name());
		_pivotBEdit->setText(StringFromVector(_hingeRestraint->pivotB()));
		_axisBEdit->setText(StringFromVector(_hingeRestraint->axisB()));

		_hingeAngleSpinBox->setValue(_hingeRestraint->hingeAngle());
		const BRealRange& angularLimit = _hingeRestraint->angularLimit();
		_angleLowSpinBox->setValue(angularLimit.min());
		_angleHighSpinBox->setValue(angularLimit.max());

		_motorSwitchButton->setChecked(_hingeRestraint->motorEnabled());
		_motorTargetSpinBox->setValue(_hingeRestraint->motorTarget());
		_motorVelocitySpinBox->setValue(_hingeRestraint->motorVelocity());
		_motorMaxMaxForceSpinBox->setValue(_hingeRestraint->motorMaxForce());
	}
}

void HingeRestraintPanel::slotNameAEditFinished(BObject* object, const BValue& value)
{
	const BString& name = value;
	_hingeRestraint->bodyA()->setName(name);
}
void HingeRestraintPanel::slotPivotAEditFinished(BObject* object, const BValue& value)
{
	const BString& text = value;
	BVector pivotA = StringToVector(text);
	_hingeRestraint->setPivotA(pivotA);
}
void HingeRestraintPanel::slotAxisAEditFinished(BObject* object, const BValue& value)
{
	const BString& text = value;
	const BVector& axisA = StringToVector(text);
	_hingeRestraint->setAxisA(axisA);
}
void HingeRestraintPanel::slotNameBEditFinished(BObject* object, const BValue& value)
{
	const BString& name = value;
	_hingeRestraint->bodyB()->setName(name);
}
void HingeRestraintPanel::slotPivotBEditFinished(BObject* object, const BValue& value)
{
	const BString& text = value;
	BVector pivotB = StringToVector(text);
	_hingeRestraint->setPivotB(pivotB);
}
void HingeRestraintPanel::slotAxisBEditFinished(BObject* object, const BValue& value)
{
	const BString& text = value;
	const BVector& axisB = StringToVector(text);
	_hingeRestraint->setAxisB(axisB);
}

void HingeRestraintPanel::slotAngleRangeEditFinished(BObject* object, const BValue& value)
{
	BReal low = _angleLowSpinBox->value();
	BReal high = _angleHighSpinBox->value();
	_hingeRestraint->setAngularLimit(BRealRange(low, high));
}

void HingeRestraintPanel::slotMotorSwitchBoxToggled(BObject* object, const BValue& value)
{
	bool motorEnabled = value;
	_hingeRestraint->setMotorEnabled(motorEnabled);
}
void HingeRestraintPanel::slotMotorTargetSliding(BObject* object, const BValue& value)
{
	BReal target = value;
	_motorTargetSpinBox->setValue(target);
	_hingeRestraint->setMotorTarget(bDTR(target));
}
void HingeRestraintPanel::slotMotorTargetEditFinished(BObject* object, const BValue& value)
{
	BReal target = value;
	_motorTargetSlider->setValue(target);
	_hingeRestraint->setMotorTarget(bDTR(target));
}
void HingeRestraintPanel::slotMotorVelocityEditFinished(BObject* object, const BValue& value)
{
	BReal motorVelocity = value;
	_hingeRestraint->setMotorVelocity(bDTR(motorVelocity));
}
void HingeRestraintPanel::slotMotorMaxForceEditFinished(BObject* object, const BValue& value)
{
	BReal motorMaxForce = value;
	_hingeRestraint->setMotorMaxForce(bDTR(motorMaxForce));
}

void HingeRestraintPanel::updateEvent(const BEvent& event)
{
	if (_hingeRestraint)
	{
		_hingeAngleSpinBox->setValue(_hingeRestraint->hingeAngle());
	}
}
